﻿#include <sstream>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

using namespace sf;

const int NUM_BRANCHES = 6;
Sprite branches[NUM_BRANCHES];

// 玩家/枝杈在哪？
// 左侧还是右侧
enum class side { LEFT, RIGHT, NONE };
side branchPositions[NUM_BRANCHES];

// 函数声明
void updateBranches(int seed)
{
	// 把所有树杈移到一个位置
	for (int j = NUM_BRANCHES - 1; j > 0; j--)
	{
		branchPositions[j] = branchPositions[j - 1];
	}

	// 在位置为0处生成新枝杈
	// 取LEFT、RIGHT、NONE?
	srand((int)time(0) + seed);
	int r = (rand() % 5);
	switch (r)
	{
	case 0:
		branchPositions[0] = side::LEFT;
		break;
	case 1:
		branchPositions[0] = side::RIGHT;
		break;
	default:
		branchPositions[0] = side::NONE;
		break;
	}
}


int main()
{
	VideoMode vm(1920, 1080);

	RenderWindow window(vm, "Timber!!!", Style::Fullscreen);

	// 创建Texture对象以便在GPU中保存图片
	Texture textureBackground;
	// 向此对象中加载图片
	textureBackground.loadFromFile("graphics/background.png");
	// 创建Sprite对象
	Sprite spriteBackground;
	// 让Sprite对象与Texture对象建立关联
	spriteBackground.setTexture(textureBackground);
	// 让spriteBackground占据整个屏幕
	spriteBackground.setPosition(0, 0);

	// 构建树精灵
	Texture textureTree;
	textureTree.loadFromFile("graphics/tree.png");
	Sprite spriteTree;
	spriteTree.setTexture(textureTree);
	const float TREE_HORIZONTAL_POSITION = 810;
	const float TREE_VERTICAL_POSITION = 0;
	spriteTree.setPosition(TREE_HORIZONTAL_POSITION, TREE_VERTICAL_POSITION);

	// 构建蜜蜂精灵
	Texture textureBee;
	textureBee.loadFromFile("graphics/bee.png");
	Sprite spriteBee;
	spriteBee.setTexture(textureBee);
	spriteBee.setPosition(0, 800);

	// 蜜蜂当前能否移动？
	bool beeActive = false;
	// 蜜蜂的飞行速度
	float beeSpeed = 0.0f;

	// 通过一个纹理对象构建三个云朵对象
	Texture textureCloud;
	// 加载新纹理
	textureCloud.loadFromFile("graphics/cloud.png");

	const int NUM_CLOUDS = 6;
	Sprite clouds[NUM_CLOUDS];
	int cloudSpeeds[NUM_CLOUDS];
	bool cloudsActive[NUM_CLOUDS];

	for (int i = 0; i < NUM_CLOUDS; i++)
	{
		clouds[i].setTexture(textureCloud);
		clouds[i].setPosition(-300, i * 150);
		cloudsActive[i] = false;
		cloudSpeeds[i] = 0;
	}

	//// 三个纹理相同的新精灵
	//Sprite spriteCloud1;
	//Sprite spriteCloud2;
	//Sprite spriteCloud3;
	//spriteCloud1.setTexture(textureCloud);
	//spriteCloud2.setTexture(textureCloud);
	//spriteCloud3.setTexture(textureCloud);

	//// 让三个云朵精灵位于屏幕左端不同高度上
	//spriteCloud1.setPosition(0, 0);
	//spriteCloud2.setPosition(0, 250);
	//spriteCloud3.setPosition(0, 500);

	//// 云朵是否处于屏幕内
	//bool clound1Active = false;
	//bool clound2Active = false;
	//bool clound3Active = false;

	//// 云朵精灵的移动速度
	//float clound1Speed = 0.0f;
	//float clound2Speed = 0.0f;
	//float clound3Speed = 0.0f;

	// 控制时间的变量
	Clock clock;

	// 时间棒
	RectangleShape timeBar;
	float timeBarStartWidth = 400;
	float timeBarHeight = 80;
	timeBar.setSize(Vector2f(timeBarStartWidth, timeBarHeight));
	timeBar.setFillColor(Color::Red);
	timeBar.setPosition((1920 / 2) - timeBarStartWidth / 2, 980);

	Time gameTimeTotal;
	float timeRemaining = 6.0f;
	float timeBarWidthPerSecond = timeBarStartWidth / timeRemaining;

	// 跟踪游戏是否在运行
	bool paused = true;

	// 绘制一些文本
	int score = 0;

	Text messageText;
	Text scoreText;

	// 需要选择字体
	Font font;
	font.loadFromFile("fonts/KOMIKAP_.ttf");

	// 为消息设置字体
	messageText.setFont(font);
	scoreText.setFont(font);

	// 实际设置消息
	messageText.setString("Press Enter to start!");
	scoreText.setString("Score = 0");

	// 让消息大一些
	messageText.setCharacterSize(75);
	scoreText.setCharacterSize(100);

	// 选择颜色
	messageText.setFillColor(Color::White);
	scoreText.setFillColor(Color::White);

	// 放置消息文本出现在屏幕中心
	FloatRect textRect = messageText.getLocalBounds();
	messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

	messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);

	scoreText.setPosition(20, 20);

	Texture textureBranch;
	textureBranch.loadFromFile("graphics/branch.png");

	// 为每一个枝杈精灵设定纹理
	for (int i = 0; i < NUM_BRANCHES; i++)
	{
		branches[i].setTexture(textureBranch);
		branches[i].setPosition(-2000, -2000);

		// 设定精灵的原点为其中心
		// 这样在旋转时便不会改动其位置
		branches[i].setPosition(220, 20);
	}

	// 准备玩家
	Texture texturePlayer;
	texturePlayer.loadFromFile("graphics/player.png");
	Sprite spritePlayer;
	spritePlayer.setTexture(texturePlayer);
	spritePlayer.setPosition(580, 720);

	// 玩家从左侧开始
	side playerSide = side::LEFT;

	// 准备墓碑
	Texture textureRIP;
	textureRIP.loadFromFile("graphics/rip.png");
	Sprite spriteRIP;
	spriteRIP.setTexture(textureRIP);
	spriteRIP.setPosition(600, 860);

	// 准备斧头
	Texture textureAxe;
	textureAxe.loadFromFile("graphics/axe.png");
	Sprite spriteAxe;
	spriteAxe.setTexture(textureAxe);
	spriteAxe.setPosition(700, 830);

	// 让斧头与树木并列
	const float AXE_POSITION_LEFT = 700;
	const float AXE_POSITION_RIGHT = 1075;

	// 准备木料
	Texture textureLog;
	textureLog.loadFromFile("graphics/log.png");
	Sprite spriteLog;
	spriteLog.setTexture(textureLog);
	spriteLog.setPosition(810, 720);

	// 木料的辅助变量
	bool logActive = false;
	float logSpeedX = 1000;
	float logSpeedY = -1500;

	// 控制玩家输入
	bool acceptInput = false;

	// 准备声音
	SoundBuffer chopBuffer;
	chopBuffer.loadFromFile("sound/chop.wav");
	Sound chop;
	chop.setBuffer(chopBuffer);

	SoundBuffer deathBuffer;
	deathBuffer.loadFromFile("sound/death.wav");
	Sound death;
	death.setBuffer(deathBuffer);

	SoundBuffer ootBuffer;
	ootBuffer.loadFromFile("sound/out_of_time.wav");
	Sound outOfTime;
	outOfTime.setBuffer(ootBuffer);

	while (window.isOpen())
	{
		/*
		***************************************
		处理玩家的输入
		***************************************
		*/

		Event event;

		while (window.pollEvent(event))
		{
			if (event.type == Event::KeyReleased && !paused)
			{
				// 重新监听按键动作
				acceptInput = true;

				// 隐藏斧头
				spriteAxe.setPosition(2000, spriteAxe.getPosition().y);
			}
		}

		if (Keyboard::isKeyPressed(Keyboard::Escape))
		{
			window.close();
		}

		// 开始游戏
		if (Keyboard::isKeyPressed(Keyboard::Return))
		{
			paused = false;

			// 重置时间与分数
			score = 0;
			timeRemaining = 6;

			// 去除所有枝杈
			for (int i = 0; i < NUM_BRANCHES; i++)
			{
				branchPositions[i] = side::NONE;
			}

			// 隐藏墓碑
			spriteRIP.setPosition(650, 2000);

			// 令玩家就位
			spritePlayer.setPosition(580, 720);

			acceptInput = true;
		}

		// 封装玩家控制代码以仅在接受输入时加以处理
		if (acceptInput)
		{
			// TODO

			// 处理右方向键
			if (Keyboard::isKeyPressed(Keyboard::Right))
			{
				// 令玩家角色位于右侧
				playerSide = side::RIGHT;

				score++;

				// 增加剩余时间
				timeRemaining += (2.0 / score) + 0.15;

				spriteAxe.setPosition(AXE_POSITION_RIGHT, spriteAxe.getPosition().y);
				spritePlayer.setPosition(1200, 720);
				
				// 更新枝杈
				updateBranches(score);

				// 将木料置于左侧
				spriteLog.setPosition(810, 720);
				logSpeedX = -5000;
				logActive = true;

				acceptInput = false;

				// 播放砍树音效
				chop.play();
			}

			// 处理左方向键
			if (Keyboard::isKeyPressed(Keyboard::Left))
			{
				// 令玩家角色位于左侧
				playerSide = side::LEFT;

				score++;

				// 增加剩余时间
				timeRemaining += (2.0 / score) + 0.15;

				spriteAxe.setPosition(AXE_POSITION_LEFT, spriteAxe.getPosition().y);
				spritePlayer.setPosition(580, 720);

				// 更新枝杈
				updateBranches(score);

				// 设定木料
				spriteLog.setPosition(810, 720);

				logSpeedX = 5000;
				logActive = true;

				acceptInput = false;
			}
		}

		/*
		***************************************
		更新场景
		***************************************
		*/
		if (!paused)
		{
			// 测量时间
			Time dt = clock.restart();

			// 扣除所消耗的时间
			timeRemaining -= dt.asSeconds();
			// 重设时间棒的大小
			timeBar.setSize(Vector2f(timeBarWidthPerSecond * timeRemaining, timeBarHeight)); // 宽度正比于时间

			if ((timeRemaining <= 0.0f))
			{
				// 暂停游戏
				paused = true;

				// 更改显示给玩家的消息
				messageText.setString("Out of time!!");

				// 根据新文本重新定位
				FloatRect textRect = messageText.getLocalBounds();
				messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

				messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);

				// 播放超时音效
				outOfTime.play();
			}

			// 设定蜜蜂
			if (!beeActive)
			{
				// 蜜蜂的移动速度
				srand((int)time(0));
				beeSpeed = (rand() % 200) + 200;

				// 蜜蜂的移动高度
				srand((int)time(0) * 10);
				float height = (rand() % 500) + 500;
				spriteBee.setPosition(2000, height);
				beeActive = true;
			}
			else// 移动蜜蜂
			{
				spriteBee.setPosition(
					spriteBee.getPosition().x - (beeSpeed * dt.asSeconds()),
					spriteBee.getPosition().y
				);
				// 蜜蜂是否到达屏幕左边界？
				if (spriteBee.getPosition().x < -100)
				{
					// 修改此蜜蜂的状态，将其在下一帧中重新出现
					beeActive = false;
				}
			}

			for (int i = 0; i < NUM_CLOUDS; i++)
			{
				if (!cloudsActive[i])
				{
					// 云朵的移动速度
					srand((int)time(0) * i);
					cloudSpeeds[i] = (rand() % 200);

					// 云朵的移动高度
					srand((int)time(0) * i);
					float height = (rand() % 150);
					clouds[i].setPosition(-200, height);
					cloudsActive[i] = true;

				}
				else
				{
					clouds[i].setPosition(
						clouds[i].getPosition().x +
						(cloudSpeeds[i] * dt.asSeconds()),
						clouds[i].getPosition().y);

					// 云朵是否到达屏幕右边界？
					if (clouds[i].getPosition().x > 1920)
					{
						// 修改此云朵的状态，将其在下一帧中重新出现
						cloudsActive[i] = false;
					}

				}

			}
			//// 管理云朵
			//// 云朵1
			//if (!clound1Active)
			//{
			//	// 云朵的移动速度
			//	srand((int)time(0) * 10);
			//	clound1Speed = (rand() % 200);

			//	// 云朵的移动高度
			//	srand((int)time(0) * 10);
			//	float height = (rand() % 150);
			//	spriteCloud1.setPosition(-200, height);
			//	clound1Active = true;
			//}
			//else
			//{
			//	spriteCloud1.setPosition(
			//		spriteCloud1.getPosition().x + (clound1Speed * dt.asSeconds()),
			//		spriteCloud1.getPosition().y
			//	);
			//	// 云朵是否到达屏幕右边界？
			//	if (spriteCloud1.getPosition().x > 1920)
			//	{
			//		// 修改此云朵的状态，将其在下一帧中重新出现
			//		clound1Active = false;
			//	}
			//}
			//// 云朵2
			//if (!clound2Active)
			//{
			//	// 云朵的移动速度
			//	srand((int)time(0) * 20);
			//	clound2Speed = (rand() % 200);

			//	// 云朵的移动高度
			//	srand((int)time(0) * 20);
			//	float height = (rand() % 300) - 150;
			//	spriteCloud2.setPosition(-200, height);
			//	clound2Active = true;
			//}
			//else
			//{
			//	spriteCloud2.setPosition(
			//		spriteCloud2.getPosition().x + (clound2Speed * dt.asSeconds()),
			//		spriteCloud2.getPosition().y
			//	);
			//	// 云朵是否到达屏幕右边界？
			//	if (spriteCloud2.getPosition().x > 1920)
			//	{
			//		// 修改此云朵的状态，将其在下一帧中重新出现
			//		clound2Active = false;
			//	}
			//}
			//// 云朵3
			//if (!clound3Active)
			//{
			//	// 云朵的移动速度
			//	srand((int)time(0) * 30);
			//	clound3Speed = (rand() % 200);

			//	// 云朵的移动高度
			//	srand((int)time(0) * 30);
			//	float height = (rand() % 450) - 150;
			//	spriteCloud3.setPosition(-200, height);
			//	clound3Active = true;
			//}
			//else
			//{
			//	spriteCloud3.setPosition(
			//		spriteCloud3.getPosition().x + (clound3Speed * dt.asSeconds()),
			//		spriteCloud3.getPosition().y
			//	);
			//	// 云朵是否到达屏幕右边界？
			//	if (spriteCloud3.getPosition().x > 1920)
			//	{
			//		// 修改此云朵的状态，将其在下一帧中重新出现
			//		clound3Active = false;
			//	}
			//}

			// 更新分数文本
			std::stringstream ss;
			ss << "Score = " << score;
			scoreText.setString(ss.str());

			// 更新枝杈精灵
			for (int i = 0; i < NUM_BRANCHES; i++)
			{
				float height = i * 150;

				if (branchPositions[i] == side::LEFT)
				{
					// 将精灵放在左侧
					branches[i].setPosition(610, height);

					// 横向翻转精灵
					branches[i].setOrigin(220, 40);
					branches[i].setRotation(180);
				}
				else if (branchPositions[i] == side::RIGHT)
				{
					// 将精灵放在右侧
					branches[i].setPosition(1330, height);

					// 重置精灵旋转角
					branches[i].setOrigin(220, 40);
					branches[i].setRotation(0);
				}
				else
				{
					// 隐藏枝杈
					branches[i].setPosition(3000, height);
				}
			}

			// 处理木料
			if (logActive)
			{
				spriteLog.setPosition(spriteLog.getPosition().x + (logSpeedX * dt.asSeconds()),
					spriteLog.getPosition().y + (logSpeedY * dt.asSeconds()));

				// 木料是否到达右边界？
				if (spriteLog.getPosition().x < -100 || spriteLog.getPosition().x > 2000)
				{
					// 调整木料设定,使其在下一帧中成为新的实例
					logActive = false;
					spriteLog.setPosition(810, 720);
				}
			}

			// 玩家是否被枝杈压扁？
			if (branchPositions[5] == playerSide)
			{
				// 死亡
				paused = true;
				acceptInput = false;

				// 绘制墓碑
				spriteRIP.setPosition(525, 760);

				// 隐藏玩家
				spritePlayer.setPosition(2000, 660);

				// 更新消息文本
				messageText.setString("SQUISHED!!");

				// 将其置于屏幕中央
				FloatRect textRect = messageText.getLocalBounds();

				messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

				messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);

				// 播放死亡音效
				death.play();
			}
		}
		/*
		***************************************
		绘制场景
		***************************************
		*/

		// 清空上一帧的内容
		window.clear();

		// 绘制游戏场景
		window.draw(spriteBackground);

		// 绘制云朵
		for (int i = 0; i < NUM_CLOUDS; i++)
		{
			window.draw(clouds[i]);
		}
		//window.draw(spriteCloud1);
		//window.draw(spriteCloud2);
		//window.draw(spriteCloud3);

		// 绘制树杈
		for (int i = 0; i < NUM_BRANCHES; i++)
		{
			window.draw(branches[i]);
		}

		// 绘制树木
		window.draw(spriteTree);

		// 绘制玩家
		window.draw(spritePlayer);

		// 绘制斧头
		window.draw(spriteAxe);

		// 绘制木料
		window.draw(spriteLog);

		// 绘制墓碑
		window.draw(spriteRIP);

		// 绘制那只昆虫
		window.draw(spriteBee);

		// 绘制分数
		window.draw(scoreText);

		// 绘制时间棒
		window.draw(timeBar);
		if (paused)
		{
			window.draw(messageText);
		}

		// 展示所绘制的全部游戏场景以及内容,有助于避免画面撕裂问题，这就是双重缓冲区技术。
		window.display();
	}

	return 0;
}